//
//  BKAUICollectionViewCalendarLayout.m
//  TestCollectionView
//
//  Created by sunshinfight@163.com on 2019/4/17.
//  Copyright © 2019 sunshinfight@163.com. All rights reserved.
//

#import "JXCalendarLayout.h"
#import <Foundation/Foundation.h>
#import "JXCalendarMonthHeaderView.h"
#import "JXCalendarItemCell.h"
#import "NSCalendar+JXCoveniences.h"

@interface JXCalendarLayout () {
    CGFloat _contentHeight;
    CGRect _oldBounds;
}
@end


@implementation JXCalendarLayout 

// - MARK: life cycle
- (instancetype)init
{
    self = [super init];
    if (self) {
        _attributess = [NSMutableArray new];
        _itemAttributess = [NSMutableArray new];
        _headAttributess = [NSMutableArray new];
        _dateDataSource = [NSMutableArray new];
        _contentHeight = 0;
        _oldBounds = CGRectZero;
        
        _sectionInsets = UIEdgeInsetsMake(0, 15, 0, 15);
        _monthHeaderInsets = UIEdgeInsetsMake(0, 15, 0, 15);
        _yearHeaderInsets = UIEdgeInsetsZero;
        _minimumInteritemSpacing = 0;
        _minimumLineSpacing = 0;
        _itemHeight = 40;
        
        // 默认为3年
        int32_t nowYear = [NSCalendar yearWithDate:NSDate.date];
        _startYear = nowYear - 1;
        _endYear = nowYear + 1;
    }
    
    return self;
}

+ (instancetype)initWithStartYear: (int32_t)start endDate:(int32_t)end
{
    JXCalendarLayout *layout = [self new];
    if ((end - start) >= 1) {   // 至少一年以上
        layout.startYear = start;
        layout.endYear = end;
    }
    return layout;
}

/**
 每行7个，每个月有个月的标识（header), 每列应该对应星期几
 */
- (void)prepareLayout
{
    const CGFloat collectionW = self.collectionView.bounds.size.width;
    
    // today
    NSDate *today = NSDate.date;
    int32_t todayDay = [NSCalendar dayWithDate:today];
    int32_t todayMonth = [NSCalendar monthWithDate:today];
    int32_t todayYear = [NSCalendar yearWithDate:today];
    
    // item的size
    const CGFloat itemW = (collectionW - _sectionInsets.left - _sectionInsets.right - _minimumInteritemSpacing*6)/7;
//    const CGFloat itemH = itemW;
    
    // header的size
    const CGFloat yearHeaderW = collectionW - _yearHeaderInsets.left - _yearHeaderInsets.right;
    const CGFloat yearHeaderH = _itemHeight;
    const CGFloat monthHeaderW = collectionW - _monthHeaderInsets.left - _monthHeaderInsets.right;
    const CGFloat monthHeaderH = _itemHeight;
    
    CGFloat currentX = _sectionInsets.left;
    NSInteger zIndex = 1;
    
    int32_t year = self.startYear;
    while (year <= self.endYear) {
        
        if (/* DISABLES CODE */ (NO)) {   // 为年单独添加header
            NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:year-self.startYear];
            UICollectionViewLayoutAttributes *headerAttrs =
            [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:JXColletionKindYear
                                                                           withIndexPath:indexPath];
            headerAttrs.zIndex = zIndex;
            
            headerAttrs.frame = CGRectMake(_yearHeaderInsets.left, _contentHeight, yearHeaderW, yearHeaderH);
            [self.headAttributess addObject:headerAttrs];
            [self.attributess addObject:headerAttrs];
            _contentHeight += yearHeaderH;
        }
        
        int month = 1;
        while (month <= 12) {
            NSString *strMonth = [NSString stringWithFormat:@"%4d-%02d-01",year, month];
            NSDate *dateMonth = [self.class dateWithString:strMonth];
            int32_t daysInMonth = [NSCalendar daysInMonthWithDate:dateMonth];
            
            NSMutableArray *monthArray = [NSMutableArray new];
            [self.dateDataSource addObject: monthArray];
            NSMutableArray *sectionArray = [NSMutableArray new];
            [self.itemAttributess addObject:sectionArray];
            
            // 为header添加属性
            UICollectionViewLayoutAttributes *headerAttrs = [UICollectionViewLayoutAttributes
                                                              layoutAttributesForSupplementaryViewOfKind:JXColletionKindMonth
                                                              withIndexPath:[NSIndexPath indexPathForItem:0 inSection:(month-1) + (year-self.startYear)*12]];
            headerAttrs.zIndex = zIndex;
            
            headerAttrs.frame = CGRectMake(_monthHeaderInsets.left, _contentHeight, monthHeaderW, monthHeaderH);
            [self.headAttributess addObject:headerAttrs];
            [self.attributess addObject:headerAttrs];
            
            _contentHeight += monthHeaderH;
            
            int32_t day = 1;
            while (day <= daysInMonth) {
                
                NSString *strDay = [NSString stringWithFormat:@"%4d-%02d-%02d",year, month, day];
                
                NSDate *dateDay = [self.class dateWithString:strDay];
                
                JXCalendarModel *model = [JXCalendarModel new];
                model.day = day;
                model.month = month;
                model.year = year;
                BOOL isToday = day == todayDay && month == todayMonth && year == todayYear;
                model.isToday = isToday;
                model.date = dateDay;
                
                [monthArray addObject:model];
                
                int weekday = [NSCalendar weekdayWithDate:dateDay];
                CGFloat interitemSpace = (weekday - 1) * _minimumInteritemSpacing;
//                CGFloat interitemSpace = 0;
                currentX = (weekday - 1) * itemW + _sectionInsets.left + interitemSpace;
                
                // item change line
                if (weekday == 1 && day != 1) {
                    _contentHeight += _itemHeight + _minimumLineSpacing;
                }
                
                NSIndexPath *indexPath = [NSIndexPath indexPathForItem:day-1
                                                             inSection:(month-1)+(year-self.startYear)*12];
                UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
                
                attrs.frame = CGRectMake(currentX, _contentHeight, itemW, _itemHeight);
                [self.attributess addObject:attrs];
                [sectionArray addObject:attrs];
                
                day++;
            }
            _contentHeight += _itemHeight;
            zIndex++;
            month++;
        }
        year++;
    }
}

+ (NSDate*)dateWithString: (NSString*)str
{
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.timeZone = NSTimeZone.localTimeZone;
    [dateFormatter setDateFormat:@"yyyy-MM-dd"];
    NSDate *date = [dateFormatter dateFromString:str];
    return date;
}

- (CGSize)collectionViewContentSize
{
    return CGSizeMake(0, _contentHeight);
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return _itemAttributess[indexPath.section][indexPath.row];
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath
{
    return _headAttributess[indexPath.section];
}


- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSMutableArray *result = [NSMutableArray new];
    BOOL stop = NO;
    for (int i = 0; i < self.attributess.count; i++) {
        UICollectionViewLayoutAttributes *attrs = self.attributess[i];
        if (rect.origin.y <= attrs.frame.origin.y || CGRectGetMaxY(rect) >= CGRectGetMaxY(attrs.frame)) {
            [result addObject:attrs];
            stop = YES;
        }
        if (stop && CGRectGetMaxY(rect) < CGRectGetMaxY(attrs.frame)) {
            break;
        }
    }
    return [result copy];
}

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
    if (CGRectEqualToRect(newBounds, _oldBounds)) {
        [self.attributess removeAllObjects];
        [self.headAttributess removeAllObjects];
        [self.itemAttributess removeAllObjects];
        [self.dateDataSource removeAllObjects];
        return YES;
    }
    return NO;
}

@end

